README

Table of Contents

1 Open Flowers (Revision '[1 1])

This is the message passing approach to the patience solitaire game Flower Garden.

This is the variant Flower Venus Garden with Laughing Flowers based on a relaxed ruleset. You can move only one card at time but from anywhere to anywhere. Sequences in the flower beds have to be build by suit. The foundations are built from ace to king but cards can be moved back into the game. You can double click a card and if possible it will find its place in the foundations. You can place up to sixteen cards in the bouquet. There is a good chance of winning the game.

(The layout of the bouquet, i.e. the reserve of cards at the bottom of the table is done automatically but only after a card has been moved successfully. Rethinking and correcting this is left as exercise for the interested player.)

2 Description & Rules

One deck of 52 cards.

< from wikipedia Thirty-six cards are dealt in to six columns, each containing six cards. The columns are called the "flower beds" and the entire tableau is sometimes called "the garden." The sixteen leftover cards become the reserve, or "the bouquet."

The top cards of each flower-bed and all of the cards in the bouquet are available for play. Cards can only be moved one at a time and can be built either on the foundations or on the other flower beds. The foundations are built up by suit, from Ace to King (a general idea of the game is to release the aces first). The cards in the garden, on the other hand, can be built down regardless of suit and any empty flower bed can be filled with any card. The cards in the bouquet can be used to aid in building, be put into the foundations, or fill an empty flower bed.

The game is won when all cards end up in the foundations. > end from wikipedia

3 NaL (Not a License)

This is free source code - free as in "free like a bird".

This is open source and marketing (which is a little bit like gardening): if someone gives you a pen at no cost and you have to refill it to write down you're favourite poem with it and someone else sings it and the producer of that song makes a whole lot of money with it then never forget: they could have used any pen to do the job. Don't break my pencils!

4 Technical Note:

While it is written in a rather traditional way without mixins, traits or an emphasis on surrogates it might contain ideas, concepts and terms that go beyond today's message passing "customs". A new message passing primitive "broadcast" and the term hub for certain classes are consequences of thinking about the future of message passing, parallel objects and one new program code abstraction system "to rule them all" especially when it comes to open source and the user's ability to adapt and program the shiny some thousand money units worth machine in front of him. From LISP machines to BSD to Mach message passing microkernel to NextStep to … but that is far away: for me it was from QBASIC to RISC assembler to NetBeans to Dr. Racket to whatever comes in handy.

5 Source Tree Layout

This implementation of Flower Garden started as one file and the one file approach ended at about 1300 lines of text. Then some parts have been cut out and are now called sections and the whole was renamed "Open Flowers". Afterwards with features like the hint system and additional animations the complexity has risen as have the prerequisites on the side of the programmer to substantially change the program.

  /Open Flowers/README.txt
    This little text.
 
  /Open FLowers/info.rkt
    PLT software package information.
 
  /Open Flowers/Open Flowers.rkt:
    Classes: stack and subclasses, garden (program action coordinator),
             flower-garden (GUI shell with menu)
    Pseudo classes: flower, flower-garden-table
 
  /Open Flowers/sections/pretext.rkt (section via include)
    The original pretext with extensions to the Algorithmic Language
    Scheme, Card Logic and debugging/developer utilities.
 
  /Open Flowers/sections/flower-dialog.rkt (module via require)
    The flower color picker. Class: flower-dialog
 
  /Open Flowers/sections/layout96l.rkt (section via include)
    The current table and card layout 9 cards wide 6 cards high with
    the foundations on the left side. Class: layout96l
 
  /Open Flowers/sections/layout77.rkt (section via include)
    The original layout 7 cards high and 7 cards wide. Class: layout77
 
  /Open Flowers/sections/layout87.rkt (section via include)
    An adaption of the original layout 8 cards high and 7 cards
    wide. Class: layout87
 
  /Open Flowers/card-faces/
    OXYGEN removed - both Oxygen and White Oxygen need some corrections
    to enhance readability. They're currently unusable. The loader is
    provided nonetheless.
 
    (This folder contains alternate card faces based on the Oxygen set
    and a loader to create a deck that can be used in Open Flowers. The
    Oxygen Card Faces are in the public domain. See the corresponding
    /svg/ files for further information.)

6 Sketch: Object Relations / Data Structure

(w/o the implicit relations of the Virtual Playing Cards Library)

  table (sfg, pseudo subclass) <1-         <1-1> flower-dialog
                                  \        /
                                   =      |
      layout hub <1- program action coordinator (sfg) ||<1-1> gui shell
                           = = =
                           | | |
   foundation (sfg)   <n-1>/ | |
   | flower-bed (sfg) <n-1>-/  | 
   | | bouquet (sfg)  <1-1>---/
   \ \ \
    \ \ n> flowers (sfg, pseudo class)
     \ n> flowers (sfg, pseudo class)
      n> flowers (sfg, pseudo class)
 
 <1-1>: a one to one relations where both objects know of each other
 object <1- object: the left object is unaware of the hosting by the
                    right object; the right object hosts one left object
 object <n-1> object: the right object can host several left objects
                    which are aware of the hosting (i.e. have a back
                    link)
 sfg: stateful game object (may be part of the game state)
 || or =: Parallel Object Interface
      The interface can handle concurrent requests.
     (In this case it manages message passing traffic with a semaphore
     and is generally not really part of the data graph. The layout hub
     is almost completely stateless at its interface, i.e. with respect
     to incoming traffic, but it is not used concurrently.)

7 Sketch: Class Hierarchy

 object
  \ \ \ \
   \ \ \ garden (program action coordinator)
    \ \ flower-garden (gui shell)
     \ stack: foundation, flower-bed, bucket
      layout96l, layout77, layout87
 
 dialog: flower-dialog
 
 Virtual Playing Cards Library Extension
  card: pseudo subclass flowers (toplevel)
  table: pseudo subclass table (in garden)

8 Message Passing (see Open Flowers.rkt)

Not each and every aspect of message passing or implemented interfaces or each and every method is well defined in the sense of a message passing protocol. But some general guidelines did exist:

Error conditions are mostly handled by using robust algorithms. The user is seen as a possible developer and there is no need to hide error messages or warnings. Exceptions are usually not caught.

Then some protocol specifications drove developement:

8.1 Protocol: Game Rules

  Higher level layers build up on lower level layers.
 
  (Layer 0: see Stateful Objects)
 
  Layer 1: low level table mechanics
   stack%:
    add-card: removes the card from all other stacks and adds it to
              this one
    remove-card: removes the card from this stack or does nothing
    move-done: the broadcast after each successful move
    number-of-cards, empty?, get-cards
 
  Layer 2: game logic (see also Parallel Objects)
   garden% (Rule Implementation Interface):
    place-on-foundation: request, predicate, private
    place-on-flower-bed: request, predicate, private
    place-on-bucket: request, predicate, private
 
  Layer 3: higher level logic / problem solvers, automatic game play
   garden% (Rule Implementation Interface)
    rescue-request
    dealers-hint

8.2 Protocol: Other Program Actions (see also Parallel Objects)

Each program action constitutes an entry point (see Parallel Objects). The shell, REPL or GUI, does nothing but communicate the program action request to the Application Interface of the program action coordinator (garden%). At first this is a one-way traffic protocol but the program action coordinator needs to communicate back to the shell to disable menu items in the GUI.

8.3 Protocol: Layout

The abstract layout hub class keeps the layout in one spot. This approach rips open the encapsulation of the other classes but in this case it's more important to seperate layout from logic.

As a general layout message passing protocol objects requesting layout information send themselves as arguments even if this is right now unecessary in some cases. In most cases though the layout hub needs more information from the object, e.g. the index of a stack to provide the correct layout information.

8.4 Protocol: Stateful Objects

Each class holding data which is part of the game state implements the Stateful Object Interface to enable the undo feature.

   save-state: Returns an unspecified data structure to be stored as
               part of the game state. It does not have to be and right
               now is not serializable. It has to be valid within one
               game (up until the next /inital-deal/.
 
   restore-state: Restores the state as saved by save state. One might
               want to add consistency checks but the stateful object
               interface is considered layer 0 with respect to the Game
               Rules Protocol and thus the restored data might be
               arbitrary data to be restored.

9 Description of the User Interaction

Most of the event handling is done by the views card<%>, table<%> and region. (See Event Handling)

According to the rules only one card may be moved at any time.

10 Parallel Objects

(Shared Unit: Display via table object / Animation System)

We need the parallel objects approach with the serializing application interface because of the nested event handling. Without this synchronization we can start a new deal, i.e. reset-game, and while its animation is running we can start another new deal via the shell's menu. Sometimes the request seems to be ignored even without synchronization but usually it's possible. At a first glance this gives us the expected behavior: the first deal is interrupted and the second new deal starts. But after the second deal completes the first deal continues usually with putting the rest of it's cards (which are kept locally in the environment of initial-deal) into the bucket. After these nested deals we are left with a lot of cards in the bucket and some empty spots within the flower bed stacks. To avoid this and other race conditions we choose to ignore user requests from the shell as long as we are busy. A better tactic would to build in the possibility to cancel the initial deal and then start the second new deal on the user's behalf.

Another issue arises with the card wiggling which shows the dealer's hint: it eventually puts the card back at the original position where the wiggle started. If we make it start a new game during the wiggling wiggle-flower-in-garden will put back the card to its original position but only after the inital deal has changed all the positions of all the other cards. Same for our window cleaner.

The current implementation does away with the mess by using a semaphore. There is second line of defence to protect against programming errors because it's easy to tinker around with the semaphore in garden class, i.e. the program action coordinator, and to use it incorrectly. That second security measure is based on a non atomic boolean. No matter if the set! operation on a boolean is atomic or not - there will always be - at least in theory - that some processor cycles long hole where we have checked the mutex but haven't set it yet. Yet this added layer of protection against misuse of the semaphore works quite well while developing. To avoid further complications when using the all purpose semaphore metapher directly we encapsulate it with two wrappers: ignore-when-busy and queue-with-busy. This is all we need and we sometimes queue events to not "block" the main thread too much. Other times we queue events because the Virtual Playing Cards Library queues events and we want to have a certain order. Queuing two callbacks consecutively seems to provoke a dead lock like behavior which might be not any more than an arbitrary restriction on how we can use the run loop but it may even be another consequence of the nested event handling creating the need to queue again. Thus we chain the queuing of the callbacks in the first place. See the implementation of the game-is-won situation.

The user requests originating from the callbacks of the Virtual Playing Cards Library need to be serialized in time, too.

NB When ignore-when-busy is called while we are busy it will display a debug level message with "code red" and ring the bell. Usually if we decide for this kind of audible feedback it would be better to implement it in the shell / application class.

11 Event Handling

There is no documented message passing protocol for the event stream coming from region and table objects. There is no well defined order but we can look at the order of events arriving and think about it. A drag starts out with a single click event. That single click event might or might not match our interactor model but we need to make its consequences unhappen because the user did not click but drag and we got to know about this only later on. There is a place to do that: see set-interactive-region-callback! in stack% add-region.

A double click is a time and coordinate dependent event usually composed of two single clicks. Depending on the libraries and low level routines in use we might expect to see the following sequences in the event stream on the same card in a short time interval: a period "." denotes a single click event, a colon ":" denotes a double click event

     ..  two clicks no double click event
     :   one double click event - no single click events
     .:  one single click event and one double click event
     ..: two single click events and one double click event
     :.. one double click event and two single click events
     .:. one single click event then a double click event then
          a single click event again

We can adapt our interaction model or Interactor (see Garnet) to avoid misinterpreting events. A single click sets the selection and the next click clears the selection. A double click clears the selection. With this behaviour in mind there remain two cases of event sequences which are not handled in the right way: the first one (..) which is degenerate because there is no double click event at all. We could try to look at the time codes of the events and determine if it was a double click or not but we cannot check the pointer coordinates here which is crucial to recognize double clicks and drags. Then the last sequence (.:.) is problematic, too. And testing suggests that this is our favourite one and only sequence of events. On the developer's machine each double click event is surrouned by single clicks and we end up with a card that has already been moved by the double click event which cleared selection and we now receive a single click event for that card: it ends up selected (in a foundation). Please bear in mind that a click event is a synthesized composed event itself: usually a click is defined as the following sequence of low level events: mouse button down, mouse button up (within the same spot region in screen coordinates). The Virtual Playing Cards Library does not use that definition of a click. Another aspect of our event handling here to keep in mind is the fact that we do not recieve a stream of events as a stream of events but the user defined thunks are invoked as event handlers at certain not well defined moments not in time but in the execution order of the Virtual Playing Cards Library routines intertwined with garbage collection and operating system interaction.

Interaction Models have to be learned by the user. Some are nowadays common accepted standard (even if not well documented) but everything changes: where you're favourite lisp based action game developing environment from back then allowed you to choose one of a set of actions and then apply it on some object today we expect to select the object.e.g. file and then choose one of its associated actions, e.g. delete. This is true on most modern graphical user interaction shells. But when you do graphic design and photo retouch we first choose the action or tool and then apply it to some part of the object to design. Vice verse these behaviours and people will tell you that it's completely broken even if they're already used to both interaction models. I don't touch I click - but that's another chapter and out of the scope of this little card game.

Some interaction models to not work out anyway: the select card then destination approach falls for Moon Flower Garden because the bucket is full of cards. Do you want to move the flower to the bucket or do you want to select a card in the bucket?

12 Animations

(outdated, see mred/15064 in Racket's bug database)

It seems the animations of the Virtual Playing Cards Library are primarily intended to visualize algorithms or better: their time ordered consequences. There is a problem where the animation of a dragged card doesn't start at the final position of the drag when/where the handler is called but it starts at the original location of the card which might be percieved as an unpleasant flickering. That behaviour of the animation engine depends on a set home-region but not only. Not setting the home-region at all in the class definition of stack% gives us the correct starting positions for the animations after a drag from the Bouquet to a Flower Bed. All drags originating from Flower Beds do still animate with the described wrong starting position. This might have to do with one of the messages in reconfigure-cards but after all: the animation engine does not feature any fine grained control and is abusing the cards<%> configuration in an undocumented way. Nevertheless the wrong starting position seems to be a real bug of the animation engine. BTW It doesn't animate snap backs either … Perhaps they want to fix it. (mred/15064)

13 Bugs and Maintenance

 Bug (mred/15065): in a new game after program start the second card in
 a flower bed which was face down could be moved. As reconfigure-cards
 in the flower-bed class is rather clear about this issue and because
 it happened during the animation of an unrelated move and is part of
 the Virtual Playing Cards Library's special behaviours.
 
 DONE -Dev: no more bangs in message passing-
 
 Bug (mred/15065): during an animation an accidental double
 click (without the final button up) onto the table background
 started a selection with a rectangle whose border was the inverse
 color of the current table background. The z-axis order of the
 cards and perhaps other things were screwed up afterwards.
 
 Bug (Mac OS X, mred/12252): Racket cancels shutdown, restart, logout.
 
 FIXED garden%: policy an all entry points: ignore when busy -Bug:
 There are still some race conditions left with the animation
 system. Put one of the aces on the foundations, ask for a new deal
 during the animation and after the next deal it ended up in the
 bucket. Then it jumped to the next foundation of the previous
 animation. Investigating stock games: Rummy does not have any other
 user controls. Spider's animations are usually to fast to enter the
 race condition but you might want to undo a move (with CMD-Z as a
 keyboard shortcut on the Mac) during the animation. Crazy 8s features
 an on-table user control: the clear button. It is blocked during
 animation. Then there is an option button in the panel but it creates
 another table on screen. Blackjack: on-table controls n/a during
 animation. Aces: undo via keyboard shortcut during animation leaves
 the cards on the stacks but face down. Clicking them provokes another
 deal onto the stacks from the deck and other non regular behavior.
 Memory and Go Fish do not have any in-game user controls.  It doesn't
 seem to be possible to protect from these race conditions completely
 as they originate from the nested event event handling of custom user
 controls and we don't know about ongoing animations in the
 Library. Perhaps some accessible mutex / semaphore on animation would
 be helpful.  It doesn't seem to be possible to protect from these race
 conditions completely as they originate from the nested event event
 handling of custom user controls and we don't know about ongoing
 animations in the Library. Perhaps some accessible mutex / semaphore
 on animation would be helpful.  The games without controls from the
 toolkit incl. menu but with on-table button regions only do not have
 that problem.-
 
 Dev: A better syntax / notation for the following sequence in
 interfaces with ignore-when-busy policy would be helpful.
  (define (proc/private ...) ...)
  (define/public (proc ...)
    (ignore-when-busy {lambda () (apply proc/private ...)}))
 Perhaps its better to seperate these interfaces or to use something
 like: {interface #:policy ignore-while-busy
                  method1 method2 ...}
 
 Dev: We cannot listen on booleans??? We need a better way to connect
 menu items with states to disable and enable them automagically.
 
 -Dev: The different layout variants are out of sync and are copy&paste
 work. Use a common-layout superclass instead. FIX Both layouts are up
 to date and usable. WONTFIX They are still copy&paste work because we
 cannot use modules with cyclic dependencies. Using the /unit/ concept
 forces us to create signature and implementation files according to a
 specific naming convention ??? That's worse than C. Managing changes
 with copy&paste is the better solution right now.-

Author: Michael Titke <mt@nPing.local>

Date: 2015/05/26 16:25:52